home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / xcdplayer / internals.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  15KB  |  696 lines

  1. /*
  2.  * Copyright (C) 1990 Regents of the University of California.
  3.  *
  4.  * Permission to use, copy, modify, distribute, and sell this software and
  5.  * its documentation for any purpose is hereby granted without fee,
  6.  * provided that the above copyright notice appear in all copies and that
  7.  * both that copyright notice and this permission notice appear in
  8.  * supporting documentation, and that the name of the University of
  9.  * California not be used in advertising or publicity pertaining to
  10.  * distribution of the software without specific, written prior
  11.  * permission.  the University of California makes no representations
  12.  * about the suitability of this software for any purpose.  It is provided
  13.  * "as is" without express or implied warranty.
  14.  */
  15.  
  16. # include <X11/Intrinsic.h>
  17. # include <X11/StringDefs.h>
  18. # include <X11/Xaw/Form.h>
  19. # include <X11/Xaw/Toggle.h>
  20.  
  21. # include <stdio.h>
  22.  
  23. # include "debug.h"
  24. # include "cdrom_globs.h"
  25. #ifdef sun
  26. # include "cdrom_sun.h"
  27. #endif
  28. #ifdef sgi
  29. # include "cdrom_sgi.h"
  30. #endif
  31.  
  32.  
  33. static XtIntervalId    ivid            = -1;
  34. static XtIntervalId    scanivid        = -1;
  35. static XtIntervalId    stativid        = -1;
  36. static unsigned int    timer_mod        = 1000 / TIMER_PERIOD;
  37. unsigned int        timer_fsecs;
  38.  
  39.  
  40. int
  41. cdrom_get_curtime() {
  42.  
  43.     int curtime;
  44.     int curtrack;
  45.     struct msf curmsf, track_start;
  46.  
  47.     if (cdrom_open() == -1) {
  48.         debug_printf(1, "cdrom_get_curtime: error from cdrom_open\n");
  49.         return;
  50.     }
  51.  
  52.     switch (cdrom_status()) {
  53.     case CDROM_PAUSED:
  54.     case CDROM_PLAYING:
  55.         if (cdrom_get_curmsf(&curmsf) == -1) {
  56.         debug_printf(1, "get_curtime: error reading location\n");
  57.         return;
  58.         }
  59.  
  60.         if (((curtrack = cdrom_get_curtrack()) == -1) ||
  61.         (curtrack != cdi.curtrack))
  62.         {
  63.         return(0);
  64.         }
  65.         else
  66.         {
  67.             track_start = cdi.addrs[cdi.curtrack - 1];
  68.             curtime = (curmsf.minute - track_start.minute) * 60 +
  69.             (curmsf.second - track_start.second) + 1;
  70.  
  71.             return (curtime);
  72.         }
  73.         break;
  74.     default:
  75.         return(0);
  76.     }
  77. }
  78.  
  79.  
  80. /*
  81.  * we poll the cd-rom drive every TIMER_PERIOD milliseconds to see where 
  82.  * it is and if it's on a new track, and update the label widget.
  83.  */
  84. void
  85. cdrom_timer_on() {
  86.     static void    update_track();
  87.  
  88.     if (cdi.state & CDROM_STATE_PLAY)
  89.         ivid = XtAppAddTimeOut(appc, TIMER_PERIOD, update_track, NULL);
  90. }
  91.  
  92.  
  93. /*
  94.  * cdrom_timer_off turns off the X timeout.
  95.  */
  96. void
  97. cdrom_timer_off() {
  98.     if (ivid != -1) {
  99.         XtRemoveTimeOut(ivid);
  100.         ivid = -1;
  101.     }
  102. }
  103.  
  104. /*
  105.  * activates player by track/index: 
  106.  */
  107. int
  108. cdrom_play() {
  109.     int    ret;
  110.  
  111.     debug_printf(1, "cdrom_play: starting track %d\n", (int) cdi.curtrack);
  112.  
  113.     track_button_update();
  114.  
  115.     if ((cdi.state & CDROM_STATE_SHUFFLE) ||
  116.         (cdi.state & CDROM_STATE_PROGRAM))
  117.         ret = cdrom_play_track(cdi.curtrack, cdi.curtrack);
  118.     else
  119.         ret = cdrom_play_track(cdi.curtrack, cdi.maxtrack);
  120.  
  121.     cdrom_timer_on();
  122.  
  123.     return(ret);
  124. }
  125.  
  126.  
  127. /*
  128.  * resets player to disc origin and turns off all modes:
  129.  */
  130. void
  131. cdrom_reset() {
  132.  
  133.     cdrom_timer_off();
  134.  
  135.     if (cdi.curtrack != 0)
  136.     {
  137.         cdi.curtrack = 1;
  138.         (void) cdrom_play(); /* force disk to beginning */
  139.  
  140.         /* 
  141.          * "pause disk" immediately; doesn't appear that you can truly
  142.          * stop the disk at origin; just stop at current location...
  143.          */
  144.         cdrom_stop();
  145.         cdi.state |= CDROM_STATE_STOP;
  146.         debug_printf(1, "cdrom_reset: forcing immediate stop\n");
  147.         leds_stop();
  148.         cdrom_timer_off();
  149.         cdi.curtrack = 0;
  150.     }
  151.  
  152.     cdi.state &= ~(CDROM_STATE_PLAY | CDROM_STATE_PAUSE | 
  153.                 CDROM_STATE_EJECTED);
  154.  
  155.     update_title();
  156.  
  157.     play_button_reset();
  158.     pause_button_reset();
  159.     timer_button_reset();
  160.  
  161.     track_button_update();
  162.     timer_button_update();
  163. }
  164.  
  165. /*
  166.  * rewinds the player through minute/second/frames:
  167.  */
  168. void
  169. cdrom_rewind () {
  170.     struct msf    track_start;
  171.         struct msf    start_addr, end_addr;
  172.     int        curtrack;
  173.     extern void     scan_update();
  174.  
  175.     if (cdrom_get_curmsf(&start_addr) == -1) {
  176.         debug_printf(1, "rew: error reading location\n");
  177.         return;
  178.     }    
  179.  
  180.     curtrack = cdrom_get_curtrack();
  181.  
  182.     if (curtrack != cdi.curtrack) 
  183.         track_button_update();
  184.  
  185.     /* find start of current track: */
  186.     track_start = cdi.addrs[curtrack - 1];
  187.  
  188.     /* 
  189.      * deal with cases where we can't back up beyond the current track: 
  190.      */
  191.     if ((curtrack == cdi.mintrack)  || 
  192.         (cdi.state & CDROM_STATE_SHUFFLE) ||
  193.         (cdi.state & CDROM_STATE_PROGRAM))
  194.     {
  195.         /* Ugh, this is ugly... (drich) */
  196.         if (((cdi.state & CDROM_STATE_PLAY) && 
  197.          ((track_start.minute * 60) + track_start.second) >=
  198.          ((start_addr.minute * 60) + start_addr.second - 
  199.           scanSkipInterval)) ||
  200.         ((cdi.state & CDROM_STATE_PAUSE) &&
  201.          ((track_start.minute * 60) + track_start.second) >=
  202.          ((start_addr.minute * 60) + start_addr.second -
  203.           pauseSkipInterval)))
  204.         {
  205.             start_addr = track_start;
  206.             start_addr.second++; /* guarantee we never back up too far */
  207.         }
  208.         else
  209.         {
  210.         if (cdi.state & CDROM_STATE_PAUSE) {
  211.             start_addr.second -= pauseSkipInterval; 
  212.         } else if (cdi.state & CDROM_STATE_PLAY) {
  213.             start_addr.second -= scanSkipInterval; 
  214.         }
  215.             if ((char) start_addr.second < 0)
  216.             {
  217.             start_addr.minute--;
  218.             start_addr.second = 60 + (char) start_addr.second; 
  219.             }
  220.         }
  221.  
  222.     }
  223.     else /* normal case */
  224.     {
  225.         if (cdi.state & CDROM_STATE_PAUSE) {
  226.             start_addr.second -= pauseSkipInterval; 
  227.         } else if (cdi.state & CDROM_STATE_PLAY) {
  228.             start_addr.second -= scanSkipInterval; 
  229.         }
  230.         if ((char) start_addr.second < 0)
  231.         {
  232.             start_addr.minute--;
  233.             start_addr.second = 60 + (char) start_addr.second; 
  234.         }
  235.     }
  236.         
  237.     if ((cdi.state & CDROM_STATE_PROGRAM) || 
  238.         (cdi.state & CDROM_STATE_SHUFFLE))
  239.     {
  240.  
  241.         /* then to end of current selection (start of next track - 1 sec) */
  242.         end_addr = cdi.addrs[cdi.curtrack]; 
  243.         end_addr.second--;         
  244.         if ((char) end_addr.second < 0)
  245.         {
  246.         end_addr.minute--;
  247.         end_addr.second = 59;
  248.         }
  249.     }
  250.     else
  251.     {
  252.  
  253.         /*
  254.          * to end of last track; array 0-based, so really index for 
  255.          * leadout addr:
  256.          */
  257.         end_addr = cdi.addrs[cdi.maxtrack];
  258.         end_addr.second--; /* go to last second */
  259.         if ((char) end_addr.second < 0)
  260.         {
  261.         end_addr.minute--;
  262.         end_addr.second = 59;
  263.         }
  264.     }
  265.  
  266.     if ((start_addr.minute == end_addr.minute) && 
  267.         (start_addr.second == end_addr.second))
  268.         end_addr.frame = start_addr.frame;
  269.  
  270.     cdrom_play_msf (&start_addr, &end_addr);
  271.  
  272.     timer_fsecs = 0;
  273.     if (cdi.state & CDROM_STATE_PAUSE)
  274.     {
  275.         if (scanivid == -1)
  276.         scanivid = XtAppAddTimeOut(appc, 
  277.             (int)(pausePauseInterval * 1000.0), 
  278.             scan_update, NULL);
  279.  
  280.         cdi.state &= ~CDROM_STATE_PAUSE;    /* allow timer to change */
  281.         timer_button_update();
  282.         cdi.state |= CDROM_STATE_PAUSE;    /* restore true state */
  283.  
  284.         if (cdrom_pause() != -1)        /* re-pause */
  285.            cdi.state &= ~CDROM_STATE_STOP;
  286.  
  287.     }
  288.     else
  289.     {
  290.         if (scanivid != -1) {
  291.         XtRemoveTimeOut(scanivid);
  292.         ivid = -1;
  293.         }
  294.         timer_button_update();
  295.     }
  296.  
  297. }
  298.  
  299. /*
  300.  * fast-forwards the player through minute/second/frames:
  301.  */
  302. void
  303. cdrom_ff () {
  304.         struct msf    start_addr, end_addr,  next_start;
  305.     char        t;
  306.     int        curtrack;
  307.     extern void     scan_update();
  308.  
  309.     if (cdrom_get_curmsf(&start_addr) == -1) {
  310.         debug_printf(1, "ff: error reading location\n");
  311.         return;
  312.     }    
  313.  
  314.     curtrack = cdrom_get_curtrack();
  315.  
  316.     if (curtrack != cdi.curtrack) 
  317.         track_button_update();
  318.  
  319.     /* find start of next track */
  320.     next_start = cdi.addrs[curtrack];
  321.         
  322.     /* 
  323.      * deal with cases where we can't fast forward beyond the current 
  324.      * track: 
  325.      */
  326.     if ((curtrack == cdi.maxtrack)  || 
  327.         (cdi.state & CDROM_STATE_SHUFFLE) ||
  328.         (cdi.state & CDROM_STATE_PROGRAM))
  329.     {
  330.         /* see if skipping ahead will go beyond the current track: */
  331.         /* Ugh, this is ugly... (drich) */
  332.         if (((cdi.state & CDROM_STATE_PLAY) && 
  333.          ((next_start.minute * 60) + next_start.second) <=
  334.          ((start_addr.minute * 60) + start_addr.second +
  335.           scanSkipInterval)) ||
  336.         ((cdi.state & CDROM_STATE_PAUSE) &&
  337.          ((next_start.minute * 60) + next_start.second) <=
  338.          ((start_addr.minute * 60) + start_addr.second +
  339.           pauseSkipInterval)))
  340.         {
  341.         
  342.             /* start at end of current track */
  343.             start_addr = next_start;
  344.             start_addr.second--;
  345.         }
  346.         else
  347.         {
  348.             if (cdi.state & CDROM_STATE_PAUSE) {
  349.                 start_addr.second += pauseSkipInterval; 
  350.             } else if (cdi.state & CDROM_STATE_PLAY) {
  351.                 start_addr.second += scanSkipInterval; 
  352.             }
  353.             if (start_addr.second >= 60)
  354.             {
  355.                 start_addr.minute++;
  356.                 start_addr.second = start_addr.second - 60;
  357.             }
  358.         }
  359.     }
  360.     else
  361.     {
  362.         if (cdi.state & CDROM_STATE_PAUSE) {
  363.         start_addr.second += pauseSkipInterval; 
  364.         } else if (cdi.state & CDROM_STATE_PLAY) {
  365.         start_addr.second += scanSkipInterval; 
  366.         }
  367.         if (start_addr.second >= 60)
  368.         {
  369.         start_addr.minute++;
  370.         start_addr.second = start_addr.second - 60;
  371.         }
  372.     }
  373.  
  374.     if ((cdi.state & CDROM_STATE_PROGRAM) || 
  375.         (cdi.state & CDROM_STATE_SHUFFLE))
  376.     {
  377.  
  378.         /* then to end of current selection */
  379.         end_addr = next_start;    /* use start of next */
  380.         end_addr.second--;         /* and back off 1 second */
  381.         if ((char) end_addr.second < 0)
  382.         {
  383.         end_addr.minute--;
  384.         end_addr.second = 59;
  385.         }
  386.     }
  387.     else
  388.     {
  389.         /* 
  390.          * "to end of last track"; array 0-based, so really index for 
  391.          * leadout addr 
  392.          */
  393.         end_addr = cdi.addrs[cdi.maxtrack];
  394.  
  395.         end_addr.second--; /* (you can't play the leadout) */
  396.         if ((char) end_addr.second < 0)
  397.         {
  398.         end_addr.minute--;
  399.         end_addr.second = 59;
  400.         }
  401.     }
  402.  
  403.     if ((start_addr.minute == end_addr.minute) && 
  404.         (start_addr.second == end_addr.second))
  405.     {
  406.         start_addr.frame = end_addr.frame = 0;
  407.     }
  408.  
  409.     cdrom_play_msf (&start_addr, &end_addr);
  410.  
  411.     timer_fsecs = 0;
  412.     if (cdi.state & CDROM_STATE_PAUSE)
  413.     {
  414.         if (scanivid == -1)
  415.         scanivid = XtAppAddTimeOut(appc, 
  416.             (int)(pausePauseInterval * 1000.0), 
  417.             scan_update, NULL);
  418.  
  419.         cdi.state &= ~CDROM_STATE_PAUSE;    /* allow timer to change */
  420.         timer_button_update();
  421.         cdi.state |= CDROM_STATE_PAUSE;    /* restore true state */
  422.  
  423.         if (cdrom_pause() != -1)        /* re-pause */
  424.            cdi.state &= ~CDROM_STATE_STOP;
  425.     }
  426.     else
  427.     {
  428.         if (scanivid != -1) {
  429.         XtRemoveTimeOut(scanivid);
  430.         ivid = -1;
  431.         }
  432.         timer_button_update();
  433.     }
  434. }
  435.  
  436.  
  437. /*
  438.  * called by update_track when the cd has hit
  439.  * the end of the track or the disc.
  440.  */
  441. static void
  442. cdrom_atend() {
  443.     cdrom_timer_off();
  444.     leds_stop();
  445.     debug_printf(1, "cdrom_atend: at end\n");
  446.  
  447. #ifdef sgi
  448.     /* Force a stop to kill the child (if any).
  449.      * This is due to some sort of weirdness when the SGI runs off the 
  450.      * disc during a CDreadda().
  451.      */
  452.     if (cdi.scsi_audio) {
  453.         cdrom_stop();
  454.     }
  455. #endif
  456.     if (cdi.state & CDROM_STATE_SHUFFLE) {
  457.  
  458.         if (cdi.currand == cdi.ntracks) {
  459.             if ((cdi.state & CDROM_STATE_CYCLE) == 0) {
  460.                 debug_printf(1, "cdrom_atend: shuffle done\n");
  461.  
  462.                 cdrom_reset();
  463.                 return;
  464.             }
  465.  
  466.             debug_printf(1, "cdrom_atend: shuffle cycling\n");
  467.             shuffle_setup();
  468.         }
  469.  
  470.         cdi.curtrack = shuffle_next_track();
  471.     }
  472.     else if (cdi.state & CDROM_STATE_PROGRAM) {
  473.         if ((cdi.curtrack = program_goto_next_track()) == 0)
  474.         {
  475.             if (cdi.state & CDROM_STATE_CYCLE)
  476.             {
  477.                 debug_printf(1, "cdrom_atend: cycling program\n");
  478.             cdi.curtrack = program_resume();
  479.             timer_fsecs = 0;
  480.             cdi.duration = 0;
  481.             timer_button_update();
  482.  
  483.             (void) cdrom_play();
  484.             }
  485.             else
  486.             {
  487.                 debug_printf(1, "cdrom_atend: all done\n");
  488.                 cdrom_reset();
  489.             }
  490.             return;
  491.         }
  492.     }
  493.             
  494.     else if ((cdi.curtrack < cdi.maxtrack) && (cdi.curtrack != 0)) {
  495.         debug_printf(1, "cdrom_atend: continuing\n");
  496.         cdi.curtrack++;
  497.     }
  498.     else if (cdi.state & CDROM_STATE_CYCLE) {
  499.         debug_printf(1, "cdrom_atend: cycling\n");
  500.         cdi.curtrack = cdi.mintrack;
  501.     }
  502.     else {
  503.         debug_printf(1, "cdrom_atend: all done\n");
  504.         buttons_reset();
  505.         cdrom_reset();
  506.         return;
  507.     }
  508.  
  509.     timer_fsecs = 0;
  510.     cdi.duration = 0;
  511.     timer_button_update();
  512.  
  513.     (void) cdrom_play();
  514. }
  515.  
  516. /*
  517.  * scan_update is called when the scan timeout fires; it updates the timer 
  518.  * and calls the label update routine.
  519.  */
  520. /*ARGSUSED*/
  521. static void
  522. scan_update(data, id)
  523.     XtPointer    *data;
  524.     XtIntervalId    *id;
  525. {
  526.     unsigned int    curtrack;
  527.     Arg    args[1];
  528.     Boolean    state;
  529.  
  530.     extern Widget    rew_button_widget;
  531.     extern Widget    ff_button_widget;
  532.  
  533.     if ((curtrack = cdrom_get_curtrack()) != cdi.curtrack) {
  534.         if (curtrack == 0) {
  535.             cdrom_atend();
  536.  
  537.             return;
  538.         }
  539.  
  540.         timer_fsecs = 0;
  541.         cdi.duration = 0;
  542.         timer_button_update();
  543.  
  544.         cdi.curtrack = curtrack;
  545.         track_button_update();
  546.     }
  547.  
  548.  
  549.     XtSetArg(args[0], XtNstate, &state);
  550.     XtGetValues(rew_button_widget, args, 1);
  551.     if (state == True)
  552.     {
  553.         cdrom_rewind();
  554.         leds_update(BACKWARDS);
  555.         if (cdi.state & CDROM_STATE_PAUSE) {
  556.             if (cdrom_pause() != -1)
  557.                  cdi.state &= ~CDROM_STATE_STOP;
  558.         }
  559.             ivid = XtAppAddTimeOut(appc, 
  560.             (int)(scanPauseInterval * 1000.0), 
  561.             scan_update, NULL);
  562.     }
  563.     else
  564.     {
  565.         leds_update(FORWARDS);
  566.         XtSetArg(args[0], XtNstate, &state);
  567.         XtGetValues(ff_button_widget, args, 1);
  568.         if (state == True)
  569.         {
  570.             cdrom_ff();
  571.             if (cdi.state & CDROM_STATE_PAUSE) {
  572.                 if (cdrom_pause() != -1)
  573.                      cdi.state &= ~CDROM_STATE_STOP;
  574.             }
  575.  
  576.             ivid = XtAppAddTimeOut(appc,
  577.                 (int)(scanPauseInterval * 1000.0),
  578.                 scan_update, NULL);
  579.         }
  580.         else if (scanivid != -1) {
  581.             XtRemoveTimeOut(scanivid);
  582.             scanivid = -1;
  583.         }
  584.     }
  585. }
  586.  
  587.  
  588. /*
  589.  * update_status is called when the status timeout fires;  it maintains
  590.  * the disc status, and will detect when a new disc has been inserted.
  591.  */
  592. /*ARGSUSED*/
  593. void
  594. update_status(data, id)
  595.     XtPointer    *data;
  596.     XtIntervalId    *id;
  597. {
  598.     if (cdi.state & CDROM_STATE_EJECTED) {
  599.         if (cdrom_open() == -1) {
  600.             debug_printf(1, "cdrom_open: cdrom not ready\n");
  601.         } else {
  602.             cdi.state &= ~CDROM_STATE_EJECTED;
  603.             buttons_reset();
  604.         }
  605.     }
  606.     
  607.     /* Reset timer */
  608.     stativid = XtAppAddTimeOut(appc, 1000, update_status, NULL);
  609. }
  610.  
  611. /*
  612.  * update_track is called when the timeout fires; it updates curtrack and 
  613.  * calls the label update routine.
  614.  */
  615. /*ARGSUSED*/
  616. static void
  617. update_track(data, id)
  618.     XtPointer    *data;
  619.     XtIntervalId    *id;
  620. {
  621.     unsigned int    curtrack;
  622.     Arg    args[1];
  623.     Boolean    state;
  624.  
  625.     extern Widget    rew_button_widget;
  626.     extern Widget    ff_button_widget;
  627. #ifdef sgi
  628.  
  629.     int    vol;
  630. #endif
  631.  
  632.     if ((curtrack = cdrom_get_curtrack()) != cdi.curtrack) {
  633.         if (curtrack == 0) {
  634.             cdrom_atend();
  635.  
  636.             return;
  637.         }
  638.  
  639.         timer_fsecs = 0;
  640.         cdi.duration = 0;
  641.         timer_button_update();
  642.  
  643.         cdi.curtrack = curtrack;
  644.         track_button_update();
  645.     }
  646.  
  647. #ifdef sgi
  648.     /* Update the volume control */
  649.     if ((vol = cdrom_get_volume()) != 0) {
  650.         set_volume(vol);
  651.     }
  652. #endif
  653.  
  654.     XtSetArg(args[0], XtNstate, &state);
  655.     XtGetValues(rew_button_widget, args, 1);
  656.     if (state == True)
  657.     {
  658.         cdrom_rewind();
  659.         leds_update(BACKWARDS);
  660.         if (cdi.state & CDROM_STATE_PAUSE) {
  661.             if (cdrom_pause() != -1)
  662.                  cdi.state &= ~CDROM_STATE_STOP;
  663.         }
  664.             ivid = XtAppAddTimeOut(appc, 
  665.             (int)(scanPauseInterval * 1000.0), 
  666.             update_track, NULL);
  667.     }
  668.     else
  669.     {
  670.         leds_update(FORWARDS);
  671.         XtSetArg(args[0], XtNstate, &state);
  672.         XtGetValues(ff_button_widget, args, 1);
  673.         if (state == True)
  674.         {
  675.             cdrom_ff();
  676.             if (cdi.state & CDROM_STATE_PAUSE) {
  677.                 if (cdrom_pause() != -1)
  678.                      cdi.state &= ~CDROM_STATE_STOP;
  679.             }
  680.  
  681.             ivid = XtAppAddTimeOut(appc,
  682.                 (int)(scanPauseInterval * 1000.0),
  683.                 update_track, NULL);
  684.         }
  685.         else
  686.         {
  687.             if ((timer_fsecs++ % timer_mod) == 0) {
  688.                 timer_button_update();
  689.             }
  690.             ivid = XtAppAddTimeOut(appc, TIMER_PERIOD, 
  691.                 update_track, NULL);
  692.         }
  693.     }
  694. }
  695.  
  696.